<template>
<main class="noselect colFlex">
  <section class="titleDiv rowFlex">
    <h1>平滑变速</h1>
  </section>

  <section class="dotInnerDiv">
    <div class="dotBox rowFlex">
      <span class="dot" ref="dot"></span>
    </div>
    <div class="dotBox rowFlex">
      <span class="dotAF" ref="dotAF"></span>
    </div>
    <div class="texBox rowFlex">
      <h2 class="rowFlex">关键帧-变速不平滑</h2>
    </div>
    <div class="texBox rowFlex">
      <h2 class="rowFlex">运动框架-平滑变速</h2>
    </div>
  </section>

  <section class="formDiv noselect">
    <div class="bpmBox rowFlex">
      <h3 class="Tex">当前速度</h3>
      <span class="bpmTex">{{ bits.bpmNum }}</span>
      <h3 class="Tex">拖滑块变速</h3>
    </div>

    <div class="slider-demo-block">
      <h4>10bpm</h4>
      <el-slider v-model="bits.bpmNum" :min="10" :max="400" :step="10" size="default" />
      <h4>400bpm</h4>
    </div>

    <div class="btDiv colFlex">
      <div class="rowFlex">
        <el-button type="primary" @click="btClick()">
          {{ btText.texts[btText.ind] }}
        </el-button>
        <el-button type="primary" @click="btClick('rest')"> 重置 </el-button>
      </div>
    </div>

  </section>
</main>
</template>

<script>
//element-Plus的slider滑块，touchstart监听未标记被动式，浏览器可能会出现警告，不影响使用，如需去除警告可更换UI。
import {
  Plus
} from "@element-plus/icons-vue";
import {
  ref
} from "vue";

export default {
  name: "speadSmooth",
  components: {
    Plus
  },
  data() {
    return {
      btText: {
        texts: ["播放", "暂停"],
        ind: 0,
      },
      bits: {
        bpmNum: ref(80),
        rowNum: 80,
        throttle: false,
      },
      records: {
        rotateTime: null,
        lastRotate: 0,
      },
    };
  },
  watch: {
    "bits.bpmNum"() {
      if (this.btText.ind == 1) {
        if (this.bits.throttle == false) {
          this.bits.throttle = true;
          setTimeout(() => {
            this.bits.throttle = false;
          }, 50);
          this.bits.rowNum = this.bits.bpmNum;

          let dot = this.$refs.dot;
          dot.style.animationDuration = (60 / this.bits.rowNum) * 4 + "s";

          let dotAF = this.$refs.dotAF;
          let reg = RegExp(/.*rotateZ\(([0-9]{1,}\.?[0-9]{1,})deg\).*/g);
          let deg = parseInt(
            dotAF.style.transform.toString().replace(reg, "$1") % 360
          );
          this.records.lastRotate = deg; //运动框架-记录旋转量
          this.records.rotateTime = new Date(); //运动框架-更新上次变速时间
        }
      }
    },
  },
  mounted() {
    //运动框架-编辑定时器
    window.requestAnimationFrame =
      window.requestAnimationFrame ||
      function (fn) {
        return setTimeout(fn, 1000 / 60);
      };
    window.cancelAnimationFrame = window.cancelAnimationFrame || clearTimeout;
  },
  methods: {
    btClick(mod) {
      this.bits.throttle = false;
      let btText = this.btText;
      let dot = this.$refs.dot;
      let dotAF = this.$refs.dotAF;

      if (mod == "rest") {
        btText.ind = 0;

        if (dot.classList.contains("dotStart")) {
          dot.classList.remove("dotStart");
        }

        setTimeout(() => {
          dot.style.animationDuration = "0s";
          dot.style.animationPlayState = "paused";
        }, 0);

        this.records.lastRotate = 0;
        dotAF.style.transform = "rotateZ(0deg)";
        return false;
      }

      if (btText.ind == 0) {
        btText.ind = 1;
        if (!dot.classList.contains("dotStart")) {
          dot.classList.add("dotStart");
        }

        dot.style.animationDuration = (60 / this.bits.rowNum) * 4 + "s";
        dot.style.animationPlayState = "running";
        this.records.rotateTime = new Date();

        this.reWTime();
      } else {
        btText.ind = 0;

        dot.style.animationPlayState = "paused";
        let reg = RegExp(/.*rotateZ\(([0-9]{1,}\.?[0-9]{1,})deg\).*/g);
        let deg = parseInt(
          dotAF.style.transform.toString().replace(reg, "$1") % 360
        );
        this.records.lastRotate = deg;
      }
    },
    reWTime() {
      if (this.btText.ind == 0) {
        return false;
      }

      let nowTime = new Date();
      let dotAF = this.$refs.dotAF;
      let {
        lastRotate,
        rotateTime
      } = this.records;

      let degPerBit = 360 / 4 / (60 / this.bits.rowNum); //每秒多少量
      let showRotate = (nowTime - rotateTime) / 1000; //上次变速到现在的累计时间
      let deg = (degPerBit * showRotate + lastRotate) % 360; //本次转动结果量

      dotAF.style.transform = "rotateZ(" + deg + "deg)";

      requestAnimationFrame(this.reWTime);
    },
  },
};
</script>

<style lang="scss" scoped>
.dotInnerDiv,
.formDiv,
.slider-demo-block {
  max-width: 900px;
}

main {
  justify-content: center;
}

h1,
h2 {
  margin: 0;
}

h4 {
  margin: 0 3vw;
}

.Tex {
  width: 5rem;
  margin: 0 0.2rem;
}

.bpmTex {
  color: rgba(0, 0, 0, 0.7);
  font-size: 1.7rem;
}

.titleDiv {
  height:calc(#{$vh} * 10 / 100);
}

.dotBox .texBox {
  justify-content: center;
}

.dotBox {
  height:calc(#{$vh} * 15 / 100);
}

.dotInnerDiv {
  width: 80vw;
  display: grid;
  grid-template-columns: 50% 50%;
}

.dot,
.dotAF {
  width: 0;
  height: 0;

  box-shadow: 0 0 7px skyblue;
  box-sizing: border-box;
  border-style: solid;
  border-color: $colorT $colorR $colorB $colorL;
}

.dotStart {
  animation: move 2s infinite linear;
  animation-duration: 0s;
  animation-play-state: paused;
}

.formDiv {
  width: 100vw;

  display: flex;
  flex-flow: column nowrap;
  justify-content: space-evenly;
  align-items: center;
}

.slider-demo-block {
  width: 80vw;
  height:calc(#{$vh} * 12 / 100);
  display: flex;
  align-items: center;
}

.btDiv {
  height:calc(#{$vh} * 15 / 100);
}

@media all and (orientation: landscape) {
  .texBox {
    height:calc(#{$vh} * 7 / 100);
  }

  .bpmBox {
    height:calc(#{$vh} * 15 / 100);
  }

  .dotInnerDiv {
    margin-top:calc(#{$vh} * 5 / 100);
  }

  .formDiv {
    margin:calc(#{$vh} * 5 / 100) 0;
    max-height:calc(#{$vh} * 30 / 100);
  }

  .dot,
  .dotAF {
    border-width: calc(#{$vh} * 0.03) calc(#{$vh} * 0.07) calc(#{$vh} * 0.07) calc(#{$vh} * 0.03);
  }
}

@media all and (orientation: portrait) {
  .dotBox {
    height:calc(#{$vh} * 12 / 100);
  }

  .texBox {
    height:calc(#{$vh} * 5 / 100);
  }

  .dotInnerDiv {
    margin-top: 0;
  }

  .formDiv {
    margin:calc(#{$vh} * 10 / 100) 0 calc(#{$vh} * 5 / 100);
    max-height:calc(#{$vh} * 20 / 100);
  }

  .dot,
  .dotAF {
    border-width: 3vw 7vw 7vw 3vw;
  }

}

@keyframes move {
  0% {
    transform: rotateZ(0deg);
  }

  100% {
    transform: rotateZ(360deg);
  }
}
</style>
